package com.carrot.auth.interceptor;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.carrot.auth.annotation.RequireCurrentUser;
import com.carrot.auth.constants.JwtConstants;
import com.carrot.auth.entity.LoginUserInfo;
import com.carrot.auth.holder.UserContextHolder;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;

/**
 * 用户权限拦截器,支持自解析 jwt token
 *
 * @author liuhongzhen
 */
@Slf4j
public class UserAuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {

        if (handler instanceof ResourceHttpRequestHandler) {
            return true;
        }

        try {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            RequireCurrentUser methodAnnotation = handlerMethod.getMethodAnnotation(RequireCurrentUser.class);
            if (methodAnnotation == null || !methodAnnotation.needUser()) {
                return true;
            }

            String encodeUserInfo = request.getHeader(JwtConstants.USER_INFO_HEADER);
            // 解密处理
            String userInfoStr = null;
            if (StrUtil.isEmpty(encodeUserInfo) && null != request.getCookies()) {
                for (Cookie cookie : request.getCookies()) {
                    if (cookie.getName().equals(JwtConstants.USER_INFO_HEADER)) {
                        encodeUserInfo = cookie.getValue();
                        break;
                    }
                }
            }
            // 解码
            if (StrUtil.isNotEmpty(encodeUserInfo)) {
                userInfoStr = Base64.decodeStr(encodeUserInfo);
            }
            if (JSONUtil.isTypeJSON(userInfoStr)) {
                // 上下文属性保存
                LoginUserInfo loginUserInfo = JSONUtil.toBean(userInfoStr, LoginUserInfo.class);
                UserContextHolder.setCurrUser(loginUserInfo);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return true;
    }

    @Override
    public void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        // 上下文属性值清除，防止内存泄漏
        UserContextHolder.clear();
    }

}
